import javascript

/** Gets a data flow node that represents an instance of `swagger-node`. */
DataFlow::Node swaggerInstance() {
  result = DataFlow::moduleImport("swagger-node-express")
  or
  result.getAPredecessor() = swaggerInstance()
  or
  result.(DataFlow::CallNode).getACallee().getAReturnedExpr() = swaggerInstance().asExpr()
  or
  result.(DataFlow::MethodCallNode).calls(swaggerInstance(), "createNew")
}

/** An Express route handler installed via `swagger-node`. */
class SwaggerRouteHandler extends Express::RouteHandler, DataFlow::FunctionNode {
  SwaggerRouteHandler() {
    exists(DataFlow::MethodCallNode addGet, DataFlow::ObjectLiteralNode resource |
      addGet.calls(swaggerInstance(), "addGet") and
      resource = addGet.getArgument(0).getALocalSource() and
      this = resource.getAPropertySource("action")
    )
  }

  override SimpleParameter getRouteHandlerParameter(string kind) {
    kind = "request" and result = getParameter(0).getParameter()
    or
    kind = "response" and result = getParameter(1).getParameter()
  }

  override HTTP::HeaderDefinition getAResponseHeader(string name) { none() }
}

from SwaggerRouteHandler rh, PropAccess send
where send.accesses(rh.getAResponseExpr(), "send")
select send
